<?php
/*
 * Springnote.com Mashup API PHP Library
 * 
 * 이 라이브러리는 PEAR의 HTTP_Request 에 의존하고 있다.
 * PEAR가 있는 디렉토리가 include_path에 지정돼 있어야 한다.
 */

require_once 'PEAR.php';
require_once 'HTTP/Request.php';

// Springnote OpenAPI 기본 서버 주소
if (!defined('SPRINGNOTE_API_DOMAIN')) {
	define('SPRINGNOTE_API_DOMAIN', 'api.springnote.com');
}

// Springnote OpenAPI 기본 서버 포트
if (!defined('SPRINGNOTE_API_PORT')) {
	define('SPRINGNOTE_API_PORT', 80);
}

/**
 * UTF-8 기준 XML 엔티티 변환
 * @param string $str XML 넣을 문자열
 * @return string 특수문자를 엔티티로 변환한 문자열
 */
function xmlentities($str) {
	return htmlentities($str, ENT_QUOTES, 'UTF-8');
}

/**
 * 스프링노트 접속정보 초기화 객체
 * 
 * @param string $openid 접속자의 OpenID http://.../ 형태의 Full URL을 써줘야한다.
 * @param string $userkey 사용자 키. 스프링노트의 "설정"페이지에서 볼수 있다.
 * @param int $appid 애플리케이션 ID - 개발자 키등록의 관리화면에서 볼 수 있다.
 * @param string $appkey 애플리케이션 키 - 개발자 키등록의 관리화면에서 볼 수 있다.
 * @param string $type xml과 json을 통해 값을 주고 받을 수 있다. 기본값 xml.
 * @param string $domain $openid 사용자가 아닌 다른 사용자의 Springnote 도메인으로 접속하길 원할 때 지정한다. 
 * @param string $host 스프링노트 API 기본 접속 주소. 이 값은 거의 고정적이다.
 * @param int $port 스프링노트 API 기본 접속 포트. 이 값은 거의 고정적이다.
 * @return array springnote 설정 정보
 */
function springnote_init($openid,
		$userkey,
		$appid,
		$appkey,
		$type = 'xml',
		$domain = null,
		$host = SPRINGNOTE_API_DOMAIN,
		$port = SPRINGNOTE_API_PORT) {

	$springnote = array ();

	$springnote['openid'] = $openid;
	$springnote['userkey'] = $userkey;
	$springnote['appid'] = intval($appid);
	$springnote['appkey'] = $appkey;
	$springnote['host'] = $host;
	$springnote['port'] = intval($port);
	$springnote['type'] = $type;
	$springnote['domain'] = $domain;

	return $springnote;
}

/**
 * Http Request 객체를 생성한다.
 * 
 * @param string $url 요청 URL
 * @param string $type 요청 타입 xml 혹은 json
 */
function springnote_get_request($url, $springnote, $method) {
		$req = new HTTP_Request($url);
		$req->addHeader('Content-Type', 'application/'. $springnote['type']);
		$req->setMethod($method);
		$req->setBasicAuth(springnote_generate_userid($springnote), springnote_gernerate_password($springnote));
		return $req;
}

/**
 * HTTP BASIC Auth Username 생성하기
 * @return string 인코딩된 사용자명
 */
function springnote_generate_userid($springnote) {
	return rawurlencode($springnote['openid']);
}

/**
 * HTTP BASIC Auth Password 생성하기
 */
function springnote_gernerate_password($springnote) {
	$nonce = strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 16));
	; // 16자리 16진수. 난수
	$created = gmdate('Y-m-d\TH:i:s\Z'); // 날짜 http://www.w3.org/TR/NOTE-datetime 기반 YYYY-MM-DDThh:mm:ssZ
	$keydigest = sha1($nonce . $created . $springnote['userkey'] . $springnote['appkey']); //sha1 ( nonce + created + userkey + appkey)

	$password = rawurlencode($springnote['appid'] . ',' . $nonce . ',' . $created . ',' . $keydigest);

	return $password;
}

/**
 * Url 생성하기
 * @param array $springnote 스프링노트 접속 설정정보 배열
 * @param string $pageid 페이지 ID, 없으면 모든 페이지 정보 가져오기
 * @param bool $attachment 첨부파일 가져오기 여부.
 * @param integer $aid 첨부파일 ID, 없으면 모든 첨부파일 목록
 * @return string 생성된 URL
 */
function springnote_generate_url($springnote, $pageid = null, $attachment = false, $aid = null) {
	$url = 'http://' . $springnote['host'] . ($springnote['port'] != 80 ? ':' . $springnote['port'] : '') . '/pages';

	if (!empty ($pageid)) {
		$url .= '/' . $pageid;

		if ($attachment == true) {
			$url .= '/attachments';

			if (!empty ($aid)) {
				$aid = intval($aid);
				$url .= '/' . $aid;
			}
		}
	}

	$url .= '.' . $springnote['type'];

	if (!empty ($springnote['domain'])) {
		$url .= '?domain=' . rawurlencode($springnote['domain']);
	}
	return $url;
}

/**
 * 페이지 생성하기
 * 
 * @param array $springnote Springnote 정보 페이지
 * @param string $title 페이지 제목
 * @param string $source 페이지 내용
 * @param string $rights 저작권 표시 by-nc-nd,by-nd,by-sa,by,by-nc,by-nc-sa
 * @param integer $parent_id 부모 페이지
 */
function springnote_create_page($springnote, $title, $source='', $rights='', $parent_id='') {
	$title = xmlentities($title);
	$source = xmlentities($source);
	$rights = xmlentities($rights);
	$parent_id = !empty($parent_id) ? intval($parent_id) : '';
	
	$xml_str =<<<ENDXML
<?xml version="1.0" encoding="UTF-8"?>
<page>
	<title>{$title}</title>
	<source>{$source}</source>
	<rights>{$rights}</rights>
	<relation_is_part_of type="integer">{$parent_id}</relation_is_part_of>
</page>
ENDXML;
	// 강제로 XML로 지정한다.
	$temp_springnote = $springnote;
	$temp_springnote['type'] = 'xml';
	
	$url = springnote_generate_url($temp_springnote);
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_POST);
	$req->setBody($xml_str);
	$response = $req->sendRequest();

	if (PEAR::isError($response)) {
		return $response;
	}

	return $req;
}

/**
 * 첨부 파일 생성하기 #TODO
 * 
 * @param array $springnote Springnote 정보 페이지
 * @param int $pageid 페이지번호
 * @param string $filename 파일 이름(파일의 경로와 이름)
 */
function springnote_add_attachment($springnote, $pageid, $filename) {
	if (!file_exists($filename)) {
		trigger_error($filename . ' File not found', E_USER_ERROR);
	}
	
	$pageid = intval($pageid);
	$url = springnote_generate_url($springnote, $pageid, true);
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_POST);
	
	$req->addFile('Filedata', $filename);
	
	$response = $req->sendRequest();
	
	if (PEAR::isError($response)) {
		return $response;
	}

	return $req;
}

/**
 * 페이지 혹은 페이지 목록 가져오기
 * 
 * @return mixed 오류 발생시에는 PEAR_Error 객체, 그 외의 경우는
 * 		HTTP_Request 객체를 리턴한다.
 */
function springnote_retrieve_page($springnote, $pageid = null) {
	$url = springnote_generate_url($springnote, $pageid);
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_GET);
	$response = $req->sendRequest();

	if (PEAR::isError($response)) {
		return $response;
	}

	return $req;
}

/**
 * 특정 페이지의 첨부파일 목록이나, 첨부파일을 가져온다.
 * 
 * @return mixed 오류 발생시에는 PEAR_Error 객체, 그 외의 경우는
 * 		HTTP_Request 객체를 리턴한다.
 */
function springnote_retrieve_attachment($springnote, $pageid, $aid = null) {
	$url = springnote_generate_url($springnote, $pageid, true, $aid);
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_GET);
	$response = $req->sendRequest();

	if (PEAR::isError($response)) {
		return $response;
	}

	return $req;
}

/**
 * 검색을 실행한다.
 * @param array $springnote
 * @param string $query 쿼리 문자열
 * @param boolean $fulltext true이면 본문 검색, false이면 제목만 검색
 */
function springnote_search($springnote, $query, $fulltext=true) {
	$url = springnote_generate_url($springnote, 'search');
	$param_q = '?q=' . urlencode($query);
	$param_fulltext = '&fulltext=' . ($fulltext ? 1 : 0);
	$url .= $param_q . $param_fulltext;
	
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_GET);
	$response = $req->sendRequest();

	if (PEAR::isError($response)) {
		return $response;
	}

	return $req;
}

/**
 * 특정 페이지를 수정한다.
 */
function springnote_update_page($springnote, $pageid, $title, $source, $rights=null, $parent_id='') {
	$pageid = intval($pageid);
	$parent_id = !empty($parent_id) ? intval($parent_id) : '';
	
	$xml_str =<<<ENDXML
<?xml version="1.0" encoding="utf-8"?>
<page>
ENDXML;
	
	if (!is_null($title)) {
		$title = xmlentities($title);
		$xml_str .= "<title>" . $title . "</title>\n";
	}
	
	if (!is_null($source)) {
		$source = xmlentities($source);
		$xml_str .= "<source>" . $source . "</source>\n";
	}
	
	if (!is_null($rights)) {
		$rights = xmlentities($rights);
		$xml_str .= "<rights>" . $rights . "</rights>\n";
	}
	
	if (!empty($parent_id)) {
		$xml_str .= "<relation_is_part_of type=\"integer\">" . $parent_id . "</relation_is_part_of>\n";
	}
	
	$xml_str .= "</page>\n";
	
	// 강제로 XML로 지정한다.
	$temp_springnote = $springnote;
	$temp_springnote['type'] = 'xml';
	
	$url = springnote_generate_url($temp_springnote, $pageid);
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_PUT);
	$req->setBody($xml_str);
	$response = $req->sendRequest();

	if (PEAR::isError($response)) {
		return $response;
	}
	
	return $req;
}

/**
 * 특정 페이지를 삭제한다.
 */
function springnote_delete_page($springnote, $pageid) {
	$url = springnote_generate_url($springnote, $pageid);
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_DELETE);
	$response = $req->sendRequest();

	if (PEAR::isError($response)) {
		return $response;
	}

	return $req;
}

/**
 * 특정 첨부 파일을 삭제한다.
 */
function springnote_delete_attachment($springnote, $pageid, $aid) {
	$url = springnote_generate_url($springnote, $pageid, true, $aid);
	$req = springnote_get_request($url, $temp_springnote, HTTP_REQUEST_METHOD_DELETE);
	$response = $req->sendRequest();

	if (PEAR::isError($response)) {
		return $response;
	}

	return $req;
}
?>